package com.message;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.base.interceptor.ContextInjectInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.format.Formatter;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;


/**
 * @author mzl
 * @desc
 */
@Configuration
public class AppConfiguration extends WebMvcConfigurationSupport {
    private static final Logger           LOG = LoggerFactory.getLogger(AppConfiguration.class);
    @Autowired
    private              WebMvcProperties webMvcProperties;
    @Autowired
    private              Environment      environment;

    @Value("${external.resource.dir}")
    private String externalResourceDir;
    @Bean
    @ConditionalOnProperty(name = "spring.http.converters.preferred-json-mapper", havingValue = "fastjson",
            matchIfMissing = false)
    public HttpMessageConverter<Object> fastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter converter  = new FastJsonHttpMessageConverter();
        List<MediaType>              mediaTypes = new ArrayList<>();
        mediaTypes.add(MediaType.APPLICATION_JSON);
        converter.setSupportedMediaTypes(mediaTypes);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.WriteMapNullValue);
        converter.setFastJsonConfig(fastJsonConfig);
        //
        return converter;
    }

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
        super.addInterceptors(registry);
        //
        ContextInjectInterceptor interceptor  = this.ctxInjector();
        InterceptorRegistration  registration = registry.addInterceptor(interceptor);
        // 排除swagger相关路径
        final String[] excludes = new String[]{"/webjars/springfox-swagger-ui/fonts/titillium-web-v6-latin-regular" +
                ".woff2",
                "/webjars/springfox-swagger-ui/fonts/source-code-pro-v7-latin-600.woff2", "/csrf", "/webjars" +
                "/springfox-swagger-ui/fonts/titillium-web-v6-latin-600.woff2",
                "/webjars/springfox-swagger-ui/fonts/source-code-pro-v7-latin-300.woff2", "/webjars/springfox-swagger" +
                "-ui/fonts/open-sans-v15-latin-700.woff2",
                "/webjars/springfox-swagger-ui/fonts/titillium-web-v6-latin-700.woff2", "/webjars/springfox-swagger" +
                "-ui/fonts/open-sans-v15-latin-regular.woff2", "/",
                "/swagger-resources", "/swagger-resources/configuration/security", "/swagger-resources/configuration" +
                "/ui", "/webjars/springfox-swagger-ui/favicon-16x16.png",
                "/webjars/springfox-swagger-ui/springfox.js", "/webjars/springfox-swagger-ui/swagger-ui-bundle.js",
                "/webjars/springfox-swagger-ui/springfox.css",
                "/webjars/springfox-swagger-ui/swagger-ui-standalone-preset.js", "/webjars/springfox-swagger-ui" +
                "/swagger-ui.css", "/favicon.ico", "/error", "/swagger-ui.html",
                "/swagger-resources/**", "/webjars/**", "static/**"};
        registration.excludePathPatterns(excludes);
        //
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //将所有/static/** 访问都映射到classpath:/static/ 目录下
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html").addResourceLocations(
                "classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations(
                "classpath:/META-INF/resources/webjars/");
        // 映射externalResourceDir目录
        registry.addResourceHandler("/external-resources/**")
                .addResourceLocations("file:" + externalResourceDir + "/");///////////////////////////////////////新增
        super.addResourceHandlers(registry);
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        CorsRegistration corsRegistration = registry.addMapping("/**");
        corsRegistration.allowedOrigins("*");
        corsRegistration.allowedMethods("PUT", "POST", "GET", "DELETE", "OPTIONS");
        corsRegistration.allowedHeaders("X-Requested-With", "X-Access-Token", "X-Upload-Auth-Token", "Origin",
                "Content-Type", "Cookie", ContextInjectInterceptor.TOKEN, ContextInjectInterceptor.URI);
        corsRegistration.exposedHeaders(ContextInjectInterceptor.TOKEN, ContextInjectInterceptor.URI,
                ContextInjectInterceptor.ERROR_CODE,
                ContextInjectInterceptor.AUTHORIZED);
    }

    @Bean
    public ContextInjectInterceptor ctxInjector() {
        return new ContextInjectInterceptor();
    }

    @Bean
    public Formatter<Date> dateFormatter() {
        return new DateFormatter() {
            @Override
            public Date parse(String text, Locale locale) throws ParseException {
                if (text.matches("\\d+")) {
                    return new Date(Long.valueOf(text));
                } else {
                    SimpleDateFormat simpleDateFormat0;
                    if (text.length() > 10) {
                        simpleDateFormat0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);
                    } else {
                        simpleDateFormat0 = new SimpleDateFormat("yyyy-MM-dd", locale);
                    }
                    return simpleDateFormat0.parse(text);
                }
            }
        };
    }

    @Configuration
    @Primary
    @EnableTransactionManagement(proxyTargetClass = false)
    protected static class TransactionManagementConfiguration {

    }
}
